package com.pshcp.api;

import com.alibaba.fastjson.JSONObject;
import com.external.hospital.chatmessage.Hospital2ChatMessageService;
import com.framework.base.PageList;
import com.framework.base.ResultBuilder;
import com.framework.base.ResultDTO;
import com.framework.common.config.CustomConf;
import com.framework.exception.BizException;
import com.framework.logaop.Log;
import com.framework.logaop.LogSourceEnum;
import com.framework.logaop.LogTypeEnum;
import com.framework.thread.ReqComTool;
import com.framework.tool.CommonTool;
import com.framework.util.DateUtil;
import com.pshcp.ao.common.CommonAO;
import com.pshcp.ao.expertdiagnosis.BindExpertDiagnosisSessionIdAO;
import com.pshcp.ao.expertdiagnosis.CloseExpertDiagnosisIMSessionAO;
import com.pshcp.ao.expertdiagnosis.ExistExpertDiagnosisSessionAO;
import com.pshcp.ao.expertdiagnosis.ExpertDiagnosisPageAO;
import com.pshcp.ao.expertdiagnosis.ExpertDiagnosisSessionStatusAO;
import com.pshcp.ao.expertdiagnosis.SetExpertDiagnosisUnReadCountAO;
import com.pshcp.ao.expertdiagnosis.SyncExpertDiagnosisIMMsgAO;
import com.pshcp.bo.ExpertDiagnosisSummaryBO;
import com.pshcp.common.enums.RegPayStatusEnum;
import com.pshcp.common.tool.PhotoTools;
import com.pshcp.doctor.ao.diagnosis.InitDoctorContactPatientAO;
import com.pshcp.domain.dto.OnlineSessionDTO;
import com.pshcp.domain.model.Doctor;
import com.pshcp.domain.model.OnlineSession;
import com.pshcp.domain.model.Patient;
import com.pshcp.domain.model.PatientOnlineOrder;
import com.pshcp.domain.model.PatientUser;
import com.pshcp.patient.business.OnlineOrderBusiness;
import com.pshcp.patient.tool.PatientTools;
import com.pshcp.service.DoctorService;
import com.pshcp.service.OnlineSessionService;
import com.pshcp.service.PatientOnlineOrderService;
import com.pshcp.service.PatientService;
import com.pshcp.service.PatientUserService;
import com.pshcp.tool.ExpertDiagnosisTool;
import com.pshcp.vo.expertdiagnosis.ExistExpertDiagnosisSessionStatusVO;
import com.pshcp.vo.expertdiagnosis.ExistExpertDiagnosisSessionVO;
import com.pshcp.vo.expertdiagnosis.ExpertDiagnosisSummaryVO;
import com.pshcp.vo.expertdiagnosis.OnlineSessionVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Description: TODO
 * @Author: xiaoche
 * @Date: 2022/12/10 20:35
 */
@Api(tags = {"通用接口-专家问诊"})
@Slf4j
@RestController
@RequestMapping("/api/expertDiagnosis")
public class ExpertDiagnosisAPI {

    @Autowired
    private OnlineSessionService onlineSessionService;

    @Autowired
    private PatientOnlineOrderService onlineOrderService;

    @Autowired
    private DoctorService doctorService;

    @Autowired
    private PatientService patientService;

    @Autowired
    private PatientUserService patientUserService;

    @Autowired
    private CustomConf customConf;

    @Autowired
    private OnlineOrderBusiness onlineOrderBusiness;
    @Autowired
    private Hospital2ChatMessageService chatMessageService;

    @Value("${custom.desc.app-name}")
    private String hosName;

    @ApiOperation("获取专家问诊概括列表(分页)")
    @Log(source = LogSourceEnum.APP, type = LogTypeEnum.SELECT, desc = "获取专家问诊概括列表(分页)")
    @PostMapping("getExpertDiagnosisSummaryPage")
    public ResultDTO<PageList<OnlineSessionVO>> getExpertDiagnosisSummaryPage(@RequestBody ExpertDiagnosisPageAO expertDiagnosisPageAO) throws BizException {
        OnlineSessionDTO onlineSessionDTO = ExpertDiagnosisTool.buildGetExpertDiagnosisPage(expertDiagnosisPageAO);
        onlineSessionDTO.setSessionStatusFlag(null);
        List<ExpertDiagnosisSummaryBO> expertDiagnosisSummaryList = onlineSessionService.getExpertDiagnosisSummaryList(onlineSessionDTO);
        List<Long> ids = expertDiagnosisSummaryList.stream().map(v -> v.getId()).collect(Collectors.toList());
        onlineSessionDTO.setIds(ids);
        PageList<OnlineSession> pageList = onlineSessionService.list(onlineSessionDTO);
        PageList<OnlineSessionVO> page = ExpertDiagnosisTool.buildGetExpertDiagnosisPage(pageList);
        buildDoctorPhoto(page.getItems());
        return ResultBuilder.success(page);
    }


    @ApiOperation("获取专家问诊列表(分页)")
    @Log(source = LogSourceEnum.APP, type = LogTypeEnum.SELECT, desc = "获取专家问诊列表(分页)")
    @PostMapping("getExpertDiagnosisPage")
    public ResultDTO<PageList<OnlineSessionVO>> getExpertDiagnosisPage(@RequestBody ExpertDiagnosisPageAO expertDiagnosisPageAO) throws BizException {
        OnlineSessionDTO onlineSessionDTO = ExpertDiagnosisTool.buildGetExpertDiagnosisPage(expertDiagnosisPageAO);
        PageList<OnlineSession> pageList = onlineSessionService.list(onlineSessionDTO);
        PageList<OnlineSessionVO> page = ExpertDiagnosisTool.buildGetExpertDiagnosisPage(pageList);
        //set head photo
        buildDoctorPhoto(page.getItems());
        return ResultBuilder.success(page);
    }

    /**
     * 设置头像
     *
     * @param vos
     */
    private void buildDoctorPhoto(List<OnlineSessionVO> vos) {
        if (CollectionUtils.isEmpty(vos)) {
            return;
        }
        List<Long> patientOnlineOrderIds = vos.stream().map(v -> v.getPatientOnlineOrderId()).collect(Collectors.toList());
        List<Long> doctorIds = vos.stream().map(v -> v.getDoctorId()).collect(Collectors.toList());
        List<Long> patientIds = vos.stream().map(v -> v.getPatientId()).collect(Collectors.toList());
        List<Long> patientUserIds = vos.stream().map(v -> v.getPatientUserId()).collect(Collectors.toList());
        List<PatientOnlineOrder> onlineOrders = onlineOrderService.findByIds(patientOnlineOrderIds);
        List<Doctor> doctors = doctorService.findByIds(doctorIds);
        List<Patient> patients = patientService.findByIds(patientIds);
        List<PatientUser> patientUsers = patientUserService.findByIds(patientUserIds);
        Map<Long, PatientOnlineOrder> patientOnlineOrderMap = onlineOrders.stream().collect(Collectors.toMap(PatientOnlineOrder::getId, Function.identity(), (key1, key2) -> key2));
        Map<Long, Patient> patientMap = patients.stream().collect(Collectors.toMap(Patient::getId, Function.identity(), (key1, key2) -> key2));
        Map<Long, String> doctorPhotoMap = doctors.stream().filter(d -> !ObjectUtils.isEmpty(d.getHeadPhoto())).collect(Collectors.toMap(d -> d.getId(), d -> d.getHeadPhoto()));
        Map<Long, String> patientUsePhotoMap = patientUsers.stream().filter(d -> !ObjectUtils.isEmpty(d.getHeadPhoto())).collect(Collectors.toMap(d -> d.getId(), d -> d.getHeadPhoto()));

        vos.forEach(item -> {
            String doctorPhoto = doctorPhotoMap.get(item.getDoctorId());
            item.setDoctorHeadPhoto(doctorPhoto);
            item.setDoctorFullHeadPhotoPath(PhotoTools.getFullPath(customConf.getFileUrl(), doctorPhoto));
            String patientUsePhoto = patientUsePhotoMap.get(item.getPatientUserId());
            item.setPatientUserHeadPhoto(patientUsePhoto);
            item.setPatientUserFullHeadPhotoPath(PhotoTools.getFullPath(customConf.getFileUrl(), patientUsePhoto));
            Patient patient = patientMap.get(item.getPatientId());
            item.setPatientSexDes(patient == null ? "未知" : PatientTools.getSexDesc(patient.getIdCardNo()));
            item.setPatientAge(patient == null ? 0 : PatientTools.getAge(patient.getIdCardNo()));
            PatientOnlineOrder patientOnlineOrder = patientOnlineOrderMap.get(item.getPatientOnlineOrderId());
            item.setDeptName(patientOnlineOrder == null ? null : patientOnlineOrder.getDeptName());
            item.setHosName(hosName);
        });
    }

    @ApiOperation("专家问诊-接诊")
    @Log(source = LogSourceEnum.APP, type = LogTypeEnum.UPDATE, desc = "专家问诊-接诊")
    @PostMapping("receptionExpertDiagnosis")
    public ResultDTO<Long> receptionExpertDiagnosis(@RequestBody CommonAO commonAO) throws BizException {
        CommonTool.checkObj(commonAO.getId(), "90000006");
        OnlineSession onlineSession = onlineSessionService.findById(commonAO.getId());
        CommonTool.checkObj(onlineSession, "90000007");
        OnlineSession receptionExpertDiagnosis = ExpertDiagnosisTool.buildReceptionExpertDiagnosis(onlineSession);
        onlineSessionService.update(receptionExpertDiagnosis);
        // 发送消息
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("content", "医生已接诊，可以进行交流了");
        jsonObject.put("doctorId", onlineSession.getDoctorId());
        jsonObject.put("doctorName", onlineSession.getDoctorName());
        Doctor doctor = doctorService.findById(onlineSession.getDoctorId());
        jsonObject.put("headUrl", PhotoTools.getFullPath(customConf.getFileUrl(), doctor.getHeadPhoto()));
        jsonObject.put("patientName", onlineSession.getPatientName());
        jsonObject.put("msgType", "10018");
        jsonObject.put("origin", "1");
        jsonObject.put("patientId", onlineSession.getPatientId());
        jsonObject.put("askType", 1);
        jsonObject.put("patientOnlineOrderId", onlineSession.getPatientOnlineOrderId());
        chatMessageService.sendMessageByType(jsonObject);
        return ResultBuilder.success(null);
    }

    @ApiOperation("专家问诊-退诊")
    @Log(source = LogSourceEnum.APP, type = LogTypeEnum.UPDATE, desc = "专家问诊-退诊")
    @PostMapping("cancelExpertDiagnosis")
    public ResultDTO<Long> cancelExpertDiagnosis(@RequestBody CommonAO commonAO) throws BizException {
        CommonTool.checkObj(commonAO.getId(), "90000006");
        OnlineSession onlineSession = onlineSessionService.findById(commonAO.getId());
        CommonTool.checkObj(onlineSession, "90000007");
        OnlineSession cancelExpertDiagnosis = ExpertDiagnosisTool.buildCancelExpertDiagnosis(onlineSession);
        onlineSessionService.update(cancelExpertDiagnosis);

        if (cancelExpertDiagnosis.getType() == 0) {
            PatientOnlineOrder onlineOrder = onlineOrderService.findById(cancelExpertDiagnosis.getPatientOnlineOrderId());
            if (RegPayStatusEnum.PAY_OK.getCode().equals(onlineOrder.getPayStatus())) {
                onlineOrder.setCancelReason("医生退诊断！");
                onlineOrderBusiness.refundOnlineOrder(onlineOrder);
            }
        }
        return ResultBuilder.success(null);
    }

    @ApiOperation("设置专家问诊未读数量")
    @Log(source = LogSourceEnum.APP, type = LogTypeEnum.SELECT, desc = "设置专家问诊未读数量")
    @PostMapping("setExpertDiagnosisUnReadCount")
    public ResultDTO<Integer> setExpertDiagnosisUnReadCount(@RequestBody SetExpertDiagnosisUnReadCountAO setExpertDiagnosisUnReadCountAO) throws BizException {
        CommonTool.checkObj(setExpertDiagnosisUnReadCountAO.getId(), "90000006");
        CommonTool.checkObj(setExpertDiagnosisUnReadCountAO.getUnReadCount(), "90000012");
        OnlineSession onlineSession = onlineSessionService.findById(setExpertDiagnosisUnReadCountAO.getId());
        CommonTool.checkObj(onlineSession, "90000007");
        OnlineSession expertDiagnosisUnReadCount = ExpertDiagnosisTool.buildSetExpertDiagnosisUnReadCount(onlineSession, setExpertDiagnosisUnReadCountAO);
        onlineSessionService.update(expertDiagnosisUnReadCount);
        return ResultBuilder.success(null);
    }

    @ApiOperation("清理专家问诊未读数量")
    @Log(source = LogSourceEnum.APP, type = LogTypeEnum.SELECT, desc = "清理专家问诊未读数量")
    @PostMapping("clearExpertDiagnosisUnReadCount")
    public ResultDTO<Integer> clearExpertDiagnosisUnReadCount(@RequestBody CommonAO commonAO) throws BizException {
        CommonTool.checkObj(commonAO.getId(), "90000006");
        OnlineSession onlineSession = onlineSessionService.findById(commonAO.getId());
        CommonTool.checkObj(onlineSession, "90000007");
        OnlineSession clearExpertDiagnosisUnReadCount = ExpertDiagnosisTool.buildClearExpertDiagnosisUnReadCount(onlineSession);
        onlineSessionService.update(clearExpertDiagnosisUnReadCount);
        return ResultBuilder.success(null);
    }

    @ApiOperation("获取专家问诊状态")
    @Log(source = LogSourceEnum.APP, type = LogTypeEnum.SELECT, desc = "获取专家问诊状态")
    @PostMapping("getExpertDiagnosisSessionStatus")
    public ResultDTO<Integer> getExpertDiagnosisSessionStatus(@RequestBody ExpertDiagnosisSessionStatusAO expertDiagnosisSessionStatusAO) throws BizException {
        CommonTool.checkString(expertDiagnosisSessionStatusAO.getSessionId(), "90000006");
        OnlineSession onlineSession = onlineSessionService.getOnlineSessionBySessionId(expertDiagnosisSessionStatusAO.getSessionId());
        CommonTool.checkObj(onlineSession, "90000007");
        return ResultBuilder.success(onlineSession.getSessionStatus());
    }

    @ApiOperation("获取是否有正在进行中的问诊")
    @Log(source = LogSourceEnum.APP, type = LogTypeEnum.SELECT, desc = "获取是否有正在进行中的问诊")
    @PostMapping("getExistExpertDiagnosisSessionList")
    public ResultDTO<List<ExistExpertDiagnosisSessionVO>> getExistExpertDiagnosisSessionList() throws BizException {
        List<OnlineSession> list = onlineSessionService.getOnlineSessionList(0, ReqComTool.getUserType(), ReqComTool.getUserId(), Arrays.asList(2, 3));
        List<ExistExpertDiagnosisSessionVO> existExpertDiagnosisSessionVOS = CommonTool.copyPropertiesList(list, ExistExpertDiagnosisSessionVO.class);
        return ResultBuilder.success(existExpertDiagnosisSessionVOS);
    }

    @ApiOperation("获取是否有正在进行中的问诊状态")
    @Log(source = LogSourceEnum.APP, type = LogTypeEnum.SELECT, desc = "获取是否有正在进行中的问诊状态")
    @PostMapping("getExistExpertDiagnosisSession")
    public ResultDTO<ExistExpertDiagnosisSessionStatusVO> getExistExpertDiagnosisSession(@RequestBody ExistExpertDiagnosisSessionAO existExpertDiagnosisSessionAO) throws BizException {
        if (ReqComTool.getUserType() == 0) {
            CommonTool.checkObj(existExpertDiagnosisSessionAO.getPatientUserId(), "90000006");
            CommonTool.checkObj(existExpertDiagnosisSessionAO.getPatientId(), "90000006");
        }
        if (ReqComTool.getUserType() == 1) {
            CommonTool.checkObj(existExpertDiagnosisSessionAO.getDoctorId(), "90000006");
            CommonTool.checkObj(existExpertDiagnosisSessionAO.getPatientId(), "90000006");
        }
        List<OnlineSession> list = onlineSessionService.getOnlineSessionList(0, ReqComTool.getUserType(), ReqComTool.getUserId(), Arrays.asList(2, 3));
        ExistExpertDiagnosisSessionStatusVO status = ExpertDiagnosisTool.buildGetExistExpertDiagnosisSession(existExpertDiagnosisSessionAO, list);
        return ResultBuilder.success(status);
    }

    @ApiOperation("专家问诊-绑定IM会话id")
    @Log(source = LogSourceEnum.APP, type = LogTypeEnum.UPDATE, desc = "专家问诊-绑定IM会话id")
    @PostMapping("bindExpertDiagnosisSessionId")
    public ResultDTO<String> bindExpertDiagnosisSessionId(@RequestBody BindExpertDiagnosisSessionIdAO bindExpertDiagnosisSessionIdAO) throws BizException {
        CommonTool.checkObj(bindExpertDiagnosisSessionIdAO.getPatientOnlineOrderId(), "90000006");
        OnlineSession onlineSession = onlineSessionService.getOnlineSessionByPatientOnlineOrderId(bindExpertDiagnosisSessionIdAO.getPatientOnlineOrderId());
        CommonTool.checkObj(onlineSession, "90000007");
        if (!StringUtils.isBlank(onlineSession.getSessionId())) {
            return ResultBuilder.success(null);
        }
        OnlineSession onlineSessionBySessionId = onlineSessionService.getOnlineSessionBySessionId(bindExpertDiagnosisSessionIdAO.getSessionId());
        if (onlineSessionBySessionId != null) {
            return ResultBuilder.success(null);
        }
        OnlineSession updateOnlineSession = ExpertDiagnosisTool.buildBindIMSessionId(onlineSession, bindExpertDiagnosisSessionIdAO);
        onlineSessionService.update(updateOnlineSession);
        return ResultBuilder.success(null);
    }

    @ApiOperation("专家问诊-结束IM会话")
    @Log(source = LogSourceEnum.APP, type = LogTypeEnum.UPDATE, desc = "专家问诊-结束IM会话")
    @PostMapping("closeExpertDiagnosisIMSession")
    public ResultDTO<String> closeExpertDiagnosisIMSession(@RequestBody CloseExpertDiagnosisIMSessionAO closeExpertDiagnosisIMSessionAO) throws BizException {
        if (ReqComTool.getUserType() != 0) {
            return ResultBuilder.failure("90000014");
        }
        CommonTool.checkObj(closeExpertDiagnosisIMSessionAO.getPatientOnlineOrderId(), "90000006");
        OnlineSession onlineSession = onlineSessionService.getOnlineSessionByPatientOnlineOrderId(closeExpertDiagnosisIMSessionAO.getPatientOnlineOrderId());
        CommonTool.checkObj(onlineSession, "90000007");
        if (onlineSession.getSessionStatus() >= 2) {
            return ResultBuilder.failure("90000011");
        }
        OnlineSession updateOnlineSession = ExpertDiagnosisTool.buildCloseExpertDiagnosisIMSession(onlineSession);
        onlineSessionService.update(updateOnlineSession);
        //close online order status
        onlineOrderService.closeOnlineOrder(onlineSession.getPatientOnlineOrderId());
        return ResultBuilder.success(null);

    }

    @ApiOperation("专家问诊-同步最新信息")
    @Log(source = LogSourceEnum.APP, type = LogTypeEnum.UPDATE, desc = "专家问诊-同步最新信息")
    @PostMapping("syncExpertDiagnosisIMMsg")
    public ResultDTO<String> syncExpertDiagnosisIMMsg(@RequestBody SyncExpertDiagnosisIMMsgAO syncExpertDiagnosisIMMsgAO) throws BizException {
        CommonTool.checkObj(syncExpertDiagnosisIMMsgAO.getPatientOnlineOrderId(), "90000006");
        OnlineSession onlineSession = onlineSessionService.getOnlineSessionByPatientOnlineOrderId(syncExpertDiagnosisIMMsgAO.getPatientOnlineOrderId());
        CommonTool.checkObj(onlineSession, "90000007");
        OnlineSession updateOnlineSession = ExpertDiagnosisTool.buildSyncExpertDiagnosisIMMsg(onlineSession, syncExpertDiagnosisIMMsgAO);
        onlineSessionService.update(updateOnlineSession);
        return ResultBuilder.success(null);
    }

    @ApiOperation("删除专家问诊信息")
    @Log(source = LogSourceEnum.APP, type = LogTypeEnum.SELECT, desc = "删除专家问诊信息")
    @PostMapping("delExpertDiagnosis")
    public ResultDTO<Long> delExpertDiagnosis(@RequestBody CommonAO commonAO) throws BizException {
        CommonTool.checkObj(commonAO.getId(), "90000006");
        OnlineSession onlineSession = onlineSessionService.findById(commonAO.getId());
        CommonTool.checkObj(onlineSession, "90000007");
        OnlineSession delExpertDiagnosis = ExpertDiagnosisTool.buildDelExpertDiagnosis(onlineSession);
        onlineSessionService.update(delExpertDiagnosis);
        return ResultBuilder.success(null);
    }

    @ApiOperation("初始化专家联系患者")
    @Log(source = LogSourceEnum.APP, type = LogTypeEnum.UPDATE, desc = "初始化专家联系患者")
    @PostMapping("initDoctorContactPatient")
    public ResultDTO<OnlineSessionVO> initDoctorContactPatient(@RequestBody InitDoctorContactPatientAO initDoctorContactPatientAO) throws Exception {
        CommonTool.checkObj(initDoctorContactPatientAO.getPatientId(), "90000006");
        Doctor doctor = doctorService.findById(ReqComTool.getUserId());
        if (doctor == null) {
            CommonTool.throwBizException("90000007", "check doctor token is right?");
        }
        Patient patient = patientService.findById(initDoctorContactPatientAO.getPatientId());
        if (patient == null) {
            CommonTool.throwBizException("90000007", "check patient id is right?");
        }
        List<OnlineSession> list = onlineSessionService.getOnlineSessionList(1, ReqComTool.getUserType(), ReqComTool.getUserId(), Arrays.asList(2, 3));
        ExistExpertDiagnosisSessionAO existExpertDiagnosisSessionAO = new ExistExpertDiagnosisSessionAO();
        existExpertDiagnosisSessionAO.setPatientId(patient.getId());
        existExpertDiagnosisSessionAO.setPatientUserId(patient.getPatientUserId());
        existExpertDiagnosisSessionAO.setDoctorId(doctor.getId());
        ExistExpertDiagnosisSessionStatusVO status = ExpertDiagnosisTool.buildGetExistExpertDiagnosisSession(existExpertDiagnosisSessionAO, list);
        OnlineSession onlineSession = status.getStatus() == 0 ? ExpertDiagnosisTool.buildInitDoctorContactPatient(doctor, patient) : onlineSessionService.getOnlineSessionByPatientOnlineOrderId(status.getPatientOnlineOrderId());
        if (status.getStatus() == 0) {
            onlineSessionService.insert(onlineSession);
        }
        OnlineSessionVO onlineSessionVO = CommonTool.copyProperties(onlineSession, OnlineSessionVO.class);
        onlineSessionVO.setDoctorHeadPhoto(doctor.getHeadPhoto());
        return ResultBuilder.success(onlineSessionVO);
    }
}
